home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
MISC
/
COIL200
/
COIL.C
next >
Wrap
C/C++ Source or Header
|
1996-09-29
|
16KB
|
630 lines
/*
Main program for electrical self inductance of a coil.
*/
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define SING_LAYER_CIRCULAR '1'
#define MULT_LAYER_CIRCULAR '2'
#define N_TURN_CIRCULAR_LOOP '3'
#define CIRCULAR_CURRENT_SHEET '4'
#define STRAIGHT_ROUND_WIRE '5'
#define TORUS_CIRCULAR_WINDING '6'
#define TORUS_RECTANGULAR_WINDING '7'
#define SING_LAYER_SQUARE '8'
#define MULT_LAYER_SQUARE '9'
#define WIRE_GAUGE 'G'
#define INDUCTANCE 'I'
#define CAPACITY 'C'
#define FREQUENCY 'F'
#define IMPEDANCE 'Z'
#define UNITS 'U'
#define PI 3.14159265358979323846
double floor(), sqrt(), exp(), log(), pow();
double skin(), helsol(), nagaoka(), rsol(), squaresol();
double diameter = 0.0;
double length = 0.0;
double dbundle = 0.0;
double outer = 0.0;
double frequency = 0.0;
double mu = 1.0;
double L = 0.0;
double cap = 0.0;
double freq = 0.0;
double w = 0.0;
double N = 0.0;
double gauge = 0.0;
double units = 0.001;
char compute = SING_LAYER_CIRCULAR;
int pass_getnum;
extern double MACHEP; /* = 2.2e-16; */
extern double MAXNUM; /* = 1.7e38; */
extern int mono;
#ifdef __WATCOMC__
int __cdecl textinit( void );
int __cdecl textout( char *s);
#else
int textinit( void );
int textout( char *s);
#endif
char str[40];
int print( char *format, ... )
{
char line[160];
va_list arglist;
va_start( arglist, format );
vsprintf( line, format, arglist);
va_end( arglist );
return( textout( line ) );
}
char *eng ( double val )
{
static char *str = "-000.000 m";
int p, e, adp, ac;
char un;
if ( fabs( val ) < 1e-13 )
{
val = 0;
p = 0;
}
else
p = (int) floor( log10( fabs( val ) ) );
e = p % 3;
if( e < 0 )
e += 3;
p -= e;
val *= pow( 10, -p );
p /= 3;
switch( p )
{
case -4:
un = 'p';
break;
case -3:
un = 'n';
break;
case -2:
un = 'u';
break;
case -1:
un = 'm';
break;
case 0:
un = 0;
break;
case 1:
un = 'K';
break;
case 2:
un = 'M';
break;
case 3:
un = 'G';
break;
case 4:
un = 'T';
break;
default:
un = '*';
break;
}
if( val >=0 )
val += 5e-4; /* round after 3 didits */
ac = sprintf( str, "%d", (int) val );
/* 3 digits of precision */
if ( ( adp = (int) ( 1e3 * fabs( val - floor(val) ) ) ) != 0 )
ac += sprintf( str + ac, ".%03d", adp );
sprintf( str + ac, " %c", un );
return( str );
}
/* Subroutine to get value entered on keyboard
* Displays previous value and updates only if a new value is entered.
*/
void getnum( char *s, char *su, double *pd, double units, int zflag )
{
double t;
char *p;
char c;
if( pass_getnum ) return;
gloop:
p = str + sprintf( str, "%s%s" , eng( *pd ), su );
while (*--p == ' ')
*p = 0;
print( "%%ff%s %%f2(%s)%%ff ? ", s, str );
p = str;
while( (c = getch()) != '\r' && c != '\x1B' )
{
putch( c );
if( c == '\b' )
{
putch(' ');
putch('\b');
*--p = ' ';
}
else
*p++ = c;
}
*p = 0;
print( "\n" );
if( c == '\x1B' )
{
pass_getnum = 1;
return;
}
if( (str[0] == 0) && (*pd <= 0.0) )
{
t = *pd;
goto tests;
}
if( str[0] != 0 )
{
sscanf( str, "%lf", &t );
tests:
if( zflag >= 0 )
{
if( t < 0.0 )
{
print( "%%fc ? Negative value not allowed; try again.\n" );
goto gloop;
}
if( zflag )
{
if( t == 0.0 )
{
print( "%%fc ? Zero value not allowed; try again.\n" );
goto gloop;
}
}
}
*pd = t * units;
}
sprintf( str, "%s%s" , eng( *pd ), su );
p = str + strlen(str);
while (*--p == ' ')
*p = 0;
print( "%%fb%s\n", str);
}
/* Skin effect correction.
* This is a close empirical approximation to a table
* found in the CRC handbook.
*/
double skin( double d ) /* wire diameter */
{
double s;
getnum( "Frequency for skin effect [MHz]", "Hz", &frequency, 1e6, 0 );
if( frequency <= 0.0 )
return( 0.25 );
s = 0.1071 * d * sqrt(frequency);
if( s > 100.0 )
s = 7.088/s;
else
{
s = 0.00546 * pow(s,5.0);
s = 0.25 * pow( 1.0+s, -0.2 );
}
return(s);
}
main(int argc,char *argv[])
{
double b, p, d, l, a, s;
char c;
char *Z;
if( !textinit( ) )
{
printf( "\nCouldn't initialise text mode" );
printf( "\nExiting ..." );
exit( 0 );
}
if( !mono )
{
if( argc > 1 )
if( *argv[1] == '/' || *argv[1] == '-' )
{
c = tolower( *(argv[1] + 1) );
if( c == 'b' )
mono = 1;
}
}
setbuf( stdout, NULL );
print( "%%ae0\n INDUCTANCE CALCULATOR %%b0\n" );
print( "%%f4by Steve MOSHIER and Emil LAURENTIU (YO3GGH)\n" );
if( !mono )
print( "%%f7Use /b on command line for black and white\n" );
print( "%%fb\nDimension unit set to millimeter\n" );
units = 0.001;
loop:
pass_getnum = 0;
print( "%%ff\nChoose operation:\n" );
print( "\n%%fe%c%%f2 %-45s %%fe%c%%f2 %s", SING_LAYER_CIRCULAR,
"Single-layer circular solenoid of round wire",
WIRE_GAUGE, "Wire gauge calculation" );
print( "\n%%fe%c%%f2 %-45s", MULT_LAYER_CIRCULAR,
"Multilayer circular solenoid" );
print( "\n%%fe%c%%f2 %-45s %%fe%c%%f2 %s", N_TURN_CIRCULAR_LOOP,
"N-turn circular loop",
INDUCTANCE, "Inductance at resonance" );
print( "\n%%fe%c%%f2 %-45s %%fe%c%%f2 %s", CIRCULAR_CURRENT_SHEET,
"Circular solenoidal current sheet",
CAPACITY, "Capacity at resonance" );
print( "\n%%fe%c%%f2 %-45s %%fe%c%%f2 %s", STRAIGHT_ROUND_WIRE,
"Straight round wire",
FREQUENCY, "Frequency at resonance" );
print( "\n%%fe%c%%f2 %-45s %%fe%c%%f2 %s", TORUS_CIRCULAR_WINDING,
"Circular toroid, circular winding",
IMPEDANCE, "Impedance of LC" );
print( "\n%%fe%c%%f2 %-45s", TORUS_RECTANGULAR_WINDING,
"Circular torus ring, rectangular winding" );
print( "\n%%fe%c%%f2 %-45s %%fe%c%%f2 %s", SING_LAYER_SQUARE,
"Single-layer square solenoid",
UNITS, "Change unit for dimensions" );
print( "\n%%fe%c%%f2 %-45s", MULT_LAYER_SQUARE,
"Multilayer square solenoid (low precision)" );
print( " %%feEsc%%f2 Exit" );
print( "\n? (%%fe%c%%f2) ", compute );
c = toupper( getche( ) );
if( c != '\r' )
compute = c;
print( "\n\n" );
switch ( compute )
{
case '\x1B':
print( "%%f7Exiting. Have a nice day!\n" );
exit(0); /* graceful exit to monitor */
case UNITS:
getunits:
print( "%%ff\nChoose the unit for dimensions:\n" );
print( "%%fe\nM%%f2 Millimeter" );
print( "%%fe\nC%%f2 Centimeter" );
print( "%%fe\nI%%f2 Inch\n" );
c = toupper( getche( ) );
print( "\n\n" );
switch ( c )
{
case 'M':
print( "%%fbDimension unit set to millimeter\n" );
units = 0.001;
break;
case 'C':
print( "%%fbDimension unit set to centimeter\n" );
units = 0.01;
break;
case 'I':
print( "%%fbDimension unit set to inch\n" );
units = 0.0254;
break;
default:
print( "%%fcInvalid answer\n" );
goto getunits;
}
goto loop;
case WIRE_GAUGE:
getnum( "American Wire Gauge number", "B&S", &gauge, 1, -1 );
d = 0.32485 * exp( -0.11594 * gauge );
print( "%%fcWire diameter = %%fb%.3e inches (%.3f mm)\n", d, 25.4 * d );
d *= 2.54; /* convert to centimeters */
getnum( "Coil length", "m", &length, units, 0 );
getnum( "Winding thickness", "m", &dbundle, units, 0 );
if( pass_getnum ) goto loop;
b = 100 * length;
c = 100 * dbundle;
N = 1.0;
b = floor( b/d );
if( b > 0.0 )
N = b;
c = floor( c/d );
if( c > 0.0 )
N *= c;
print( "%%fc%.0lf turns will fit in this space.\n", N );
goto loop;
case CAPACITY:
getnum( "Inductance value [nH]", "H", &L, 1e-9, 1 );
getnum( "Resonance frequency [MHz]", "Hz", &freq, 1e6, 1 );
if( pass_getnum ) goto loop;
w = 2 * PI * freq;
cap = 1 / ( w * w * L );
print( "%%fc\nThe capacity = %%fb%sF\n", eng( cap ) );
goto loop;
case INDUCTANCE:
getnum( "Capacitor value [pF]", "F", &cap, 1e-12, 1 );
getnum( "Resonance frequency [MHz]", "Hz", &freq, 1e6, 1 );
if( pass_getnum ) goto loop;
w = 2 * PI * freq;
L = 1 / ( w * w * cap );
print( "%%fc\nThe inductance = %%fb%sH\n", eng( L ) );
goto loop;
case FREQUENCY:
getnum( "Inductance value [nH]", "H", &L, 1e-9, 1 );
getnum( "Capacitor value [pF]", "F", &cap, 1e-12, 1 );
if( pass_getnum ) goto loop;
freq = 1 / ( 2 * PI * sqrt ( L * cap ) );
print( "%%fc\nThe resonance frequency = %%fb%sHz\n", eng( freq ) );
goto loop;
case IMPEDANCE:
getnum( "Inductance value [nH]", "H", &L, 1e-9, 1 );
getnum( "Capacitor value [pF]", "F", &cap, 1e-12, 1 );
getnum( "Resonance frequency [MHz]", "Hz", &freq, 1e6, 1 );
if( pass_getnum ) goto loop;
w = 2 * PI * freq;
Z = strdup( eng( w * L - 1 / (w * cap) ) );
print( "%%fc\nThe LC impedance (at %sHz) = %%fb%sohm\n", eng( freq ), Z );
free( Z );
goto loop;
case MULT_LAYER_CIRCULAR: /* Thick circular solenoid */
getnum( "Average diameter", "m", &diameter, units, 0 );
getrad:
getnum( "Radial depth of winding", "m", &dbundle, units, 0 );
if( dbundle > diameter )
{
print( "%%fcDepth cannot exceed diameter. Try again.\n" );
goto getrad;
}
getnum( "Length of winding", "m", &length, units, 0 );
getnum( "Total number of turns", "", &N, 1, 1 );
d = 100 * diameter;
l = 100 * length;
a = 100 * dbundle;
L = rsol( 0.5*d, l, a, N );
break;
case TORUS_RECTANGULAR_WINDING:
/* Circular torus ring of rectangular cross section
* Ref: Skilling 1948
*/
getnum( "Inner diameter of circular torus ring", "m",
&diameter, units, 1 );
getnum( "Radial width of winding cross section", "m",
&dbundle, units, 0 );
getnum( "Height of winding cross section", "m", &length, units, 0 );
getnum( "Total number of turns", "", &N, 1, 0 );
d = 100 * diameter;
l = 100 * length;
a = 100 * dbundle;
d *= 0.5;
L = 2.0e-9 * N * N * l * log( 1.0 + a/d );
break;
case MULT_LAYER_SQUARE:
getnum( "Side of square, to center of winding thickness", "m",
&diameter, units, 1 );
getnum( "Winding length", "m", &length, units, 1 );
getnum( "Winding thickness", "m", &dbundle, units, 0 );
getnum( "Total number of turns", "", &N, 1, 0 );
d = 100 * diameter;
l = 100 * length;
a = 100 * dbundle;
if( (a+l) == 0.0 )
goto operror;
s = d/(a+l);
L = 8.e-9 * d * N * N * (log(s) + 0.2235/s + 0.726 );
break;
case SING_LAYER_SQUARE:
/* Square coil, rectangular winding cross section (thickness, length).
* Ref: Grover 1922a, CRC handbook
*/
getnum( "Side of square, to center of winding thickness", "m",
&diameter, units, 1 );
getnum( "Winding length", "m", &length, units, 1 );
getnum( "Total number of turns", "", &N, 1, 0 );
d = 100 * diameter;
l = 100 * length;
a = 100 * dbundle;
L = squaresol( d, l, N );
break;
case TORUS_CIRCULAR_WINDING:
/* Circular toroid
* Ref: CRC handbook
*/
torrad:
getnum( "Radius distance from center of torus to center of winding", "m",
&diameter, units, 0 );
getnum( "Diameter of circular winding", "m", &length, units, 0 );
if( length > 2.0*diameter )
{
print( "%%fcDiameter cannot exceed toroid diameter. Try again.\n" );
goto torrad;
}
getnum( "Total number of turns", "", &N, 1, 0 );
d = 100 * diameter;
l = 100 * length;
L = 4.0e-9 * PI * N * N * (d - sqrt(d*d - 0.25*l*l));
break;
case CIRCULAR_CURRENT_SHEET:
case SING_LAYER_CIRCULAR:
case STRAIGHT_ROUND_WIRE:
case N_TURN_CIRCULAR_LOOP:
/* Solenoid, loop, or straight wire
*/
if( compute == STRAIGHT_ROUND_WIRE ) /* straight wire */
diameter = 0.0;
else
getnum( "Diameter of winding", "m", &diameter, units, 0 );
if( compute == N_TURN_CIRCULAR_LOOP )
{ /* circular loop */
length = 0.0;
}
else
{
if( compute == STRAIGHT_ROUND_WIRE )
getnum( "Length of wire", "m", &length, units, 0 );
else
getnum( "Length of winding", "m", &length, units, 0 );
}
if( (length == 0.0) && (diameter == 0.0) )
{
L = 0.0;
break;
}
if( compute == SING_LAYER_CIRCULAR )
getnum( "Wire diameter", "m", &dbundle, units, 1 );
d = 100 * diameter;
l = 100 * length;
a = 100 * dbundle;
if( d == 0.0 )
{
/* straight */
/* Ref: CRC handbook */
print( "%%faStraight piece of wire.\n" );
getnum( "Please enter diameter of wire", "m", &dbundle, units, 1 );
a = 100 * dbundle;
print( "%%faStraight piece of wire.\n" );
L = 2.0e-9 * l * ( log(4.0*l/a) - 1.0 + skin(a) + 0.5*a/l );
break;
}
getnum( "Total number of turns", "", &N, 1, 0 );
if( l == 0.0 )
{
/* circloop */
/* Ref: CRC handbook; Snow 1952 */
print( "%%faCircular loop.\n" );
getnum( "Please enter diameter of wire or bundle of wires", "m",
&dbundle, units, 1 );
a = 100 * dbundle;
p = d/a;
/* For "natural" current distribution b = -1
* For uniform current distribution b = 0 (Litz wire)
*/
b = -1.0;
if( N <= 1.0 )
s = skin(a);
else
s = 0.25;
if( a <= 0.0 )
L = MAXNUM;
else
{
L = 2.e-9 * PI * N * N * d
* ( (1.0 + (2.0*b+1.0)/(8.0*p)) * log(8.0*p) - 2.0 + s
+ (b-1.0)*(b-2.0/3.0)/(16.0*p*p));
}
break;
}
if( compute == CIRCULAR_CURRENT_SHEET )
L = nagaoka( 0.5*d, l, N );
else
{
if( a*N > l + 1e-3 ) /* allow a 10 um tolerance */
{
print( "%%fcWire diameter too large.\n" );
goto operror;
}
L = helsol( 0.5*d, l, a, N );
}
break;
default:
goto operror;
}
if( pass_getnum ) goto loop;
print( "%%fc\nThe inductance = %%fb%sH\n", eng( L ) );
fcloop:
print( "%%ff\nCompute resonance:\n" );
print( "%%fe\nEsc%%f2 None" );
print( "%%fe\nM%%f2 Set mu for core (default 1)" );
print( "%%fe\nF%%f2 Capacity -> Frequency" );
print( "%%fe\nC%%f2 Frequency -> Capacity" );
print( "\n? (%%feEsc%%f2) " );
c = toupper( getche( ) );
print( "\n\n" );
switch ( c )
{
case '\x1B':
case '\r':
goto loop;
case 'M':
getnum( "Set the equivalent mu for inductance", "", &mu, 1, 1 );
print( "%%fc\nThe equivalent inductance = %%fb%sH\n", eng( mu * L ) );
break;
case 'F':
getnum( "Capacitor value [pF]", "F", &cap, 1e-12, 1 );
freq = 1 / ( 2 * PI * sqrt( mu * L * cap ) );
print( "%%fc\nThe resonance frequency = %%fb%sHz\n", eng( freq ) );
break;
case 'C':
getnum( "Resonance frequency [MHz]", "Hz", &freq, 1e6, 1 );
w = 2 * PI * freq;
cap = 1 / ( w * w * mu * L );
print( "%%fc\nThe capacitor value = %%fb%sF\n", eng( cap ) );
break;
default:
print( "%%fcInvalid answer\n" );
goto fcloop;
}
goto fcloop;
operror:
print( "%%fc? operator error\n" );
goto loop;
}